﻿/*
 * Author: Thomas Mattsson
 * Alexander Sjösten helped with the ReadAndValidate methods (it was a shared work)
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Final_Project.SessionData
{

    /// <summary>
    /// This class represents the Session window.
    /// Here the user enters information regarding
    /// one specific session.
    /// </summary>
    public partial class SessionForm : Form
    {
        // Local variable
        private TreatmentSession session;
        private bool closeForm = true;


        /// <summary>
        /// Default constructor that sets up Sessionform window.
        /// </summary>
        public SessionForm()
        {
            InitializeComponent();

            session = new TreatmentSession();

            InitializeGUI();
        }


        /// <summary>
        /// This method initializes the gui components.
        /// </summary>
        private void InitializeGUI()
        {
            txtDate.Text = Date.ToShortDateString();
            txtDate.Select(0, 0);
            PopulateMuscleComboBox();
        }


        /// <summary>
        /// This method reads input from the text fields and
        /// calls methods to check the input.
        /// </summary>
        /// <returns>True if all input is good, False otherwise.</returns>
        private bool ReadInput()
        {
            session.Description = txtDescription.Text;
            return (ReadAndValidatePrice() && ReadAndValidateTime() && ReadAndValidateDate());
        }


        /// <summary>
        /// This method reads the text from txtPrice and checks if
        /// the input is ok. Raises an error if something goes wrong.
        /// </summary>
        /// <returns>True if input is ok, False otherwise.</returns>
        private bool ReadAndValidatePrice()
        {
            // Local variables
            double price = 0;
        
            bool result = InputUtility.GetDouble(txtPrice.Text, out price, 0);
            if (!result)
            {
                MessageBox.Show(
                    "Felaktig inmatning i Pris",
                    "Fel",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                );
                txtPrice.Focus();
                txtPrice.SelectAll();
            }
            else
            {
                session.Price = price;
            }
            return result;
        }


        /// <summary>
        /// This method reads the text from txtTime and checks if
        /// the input is ok. Raises an error if something goes wrong.
        /// </summary>
        /// <returns>True if input is ok, False otherwise.</returns>
        private bool ReadAndValidateTime()
        {
            // Local variables
            int time = 0;

            bool result = InputUtility.GetInteger(txtTime.Text, out time, 0);
            if (!result)
            {
                MessageBox.Show(
                    "Felaktig inmatning i Tid",
                    "Fel",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                );
                txtTime.Focus();
                txtTime.SelectAll();
            }
            else
            {
                session.Time = time;
            }
            return result;
        }


        /// <summary>
        /// Reads and validates the date from the txtDate field.
        /// </summary>
        /// <returns>True if date could be read correctly, False otherwise</returns>
        private bool ReadAndValidateDate()
        {
            // Local variables
            DateTime date = DateTime.Now;

            bool result = DateTime.TryParse(txtDate.Text, out date);
            if (!result)
            {
                MessageBox.Show(
                    "Felaktig inmatning i Datum, måste vara skriven på formen YYYY-MM-DD",
                    "Fel",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                );
            }
            else
            {
                session.Date = date;
            }
            return result;
        }


        /// <summary>
        /// This method gets called every time the GUI needs
        /// to be updated with new information.
        /// </summary>
        public void UpdateGUI()
        {
            txtDate.Text = session.Date.ToShortDateString();
            txtDescription.Text = session.Description;
            txtPrice.Text = session.Price.ToString();
            txtTime.Text = session.Time.ToString();
        }


        /// <summary>
        /// This method iterates through all the muscle-categories and
        /// fills the comboBox with formatted strings without any down-scores.
        /// Also calls ClearDownScores to clean up array.
        /// </summary>
        private void PopulateMuscleComboBox()
        {
            string[] categoryStrings = GetMuscleEnumAsStrings(typeof(MuscleCategories));
            cboxMuscleCategories.Items.Clear();
            cboxMuscleCategories.Items.AddRange(categoryStrings);
        }


        /// <summary>
        /// This method checks the index of the muscle categories.
        /// </summary>
        /// <param name="index">The index to check.</param>
        /// <returns>True if index is within bounds, False otherwise.</returns>
        private bool CheckIndex(int index)
        {
            return (index >= 0);
        }


        /// <summary>
        /// Read-only property that returns todays date
        /// </summary>
        private DateTime Date
        {
            get { return DateTime.Now.Date; }
        }


        /// <summary>
        /// Property related to the session variable.
        /// </summary>
        public TreatmentSession Session
        {
            get { return session; }
            set
            {
                if (value != null)
                {
                    session = value;
                    UpdateGUI();
                }
            }
        }


        /// <summary>
        /// This method returns an array of strings containing
        /// all the names in the BackMuscles enum.
        /// </summary>
        /// <param name="muscleGroupEnum">The muscle enum to use</param>
        /// <returns>An array of strings with muscles names.</returns>
        private string[] GetMuscleEnumAsStrings(Type muscleGroupEnum)
        {
            string[] muscleStrings = Enum.GetNames(muscleGroupEnum);
            muscleStrings = ClearDownScores(muscleStrings);
            return muscleStrings;
        }


        /// <summary>
        /// This method clears any downscores in the array's strings,
        /// and returns a new array containing all the strings.
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        private string[] ClearDownScores(string[] array) {
            string[] toReturn = new string[array.Length];

            for (int i = 0; i < array.Length; i++)
                toReturn[i] = array[i].Replace("_", " ");

            return toReturn;
        }


        /// <summary>
        /// This method clears the muscle listbox and inserts
        /// the string arrays contents into it.
        /// </summary>
        /// <param name="strings">The string array containing the information.</param>
        private void UpdateMuscleListBox(string[] strings)
        {
            if (strings.Length > 0)
            {
                lboxMuscles.Items.Clear();
                lboxMuscles.Items.AddRange(strings);
            }
        }

        /// <summary>
        /// This method clears all fields to default state.
        /// </summary>
        private void ResetFields()
        {
            txtDate.Text = Date.ToShortDateString();
            txtDescription.Text = string.Empty;
            txtPrice.Text = string.Empty;
            txtTime.Text = string.Empty;
            lboxMuscles.Items.Clear();
            cboxMuscleCategories.SelectedIndex = -1;
        }


        #region Event-handlers

        /// <summary>
        /// Event-handler for the closing of the window.
        /// </summary>
        /// <param name="sender">A reference to the close button</param>
        /// <param name="e">Additional event information.</param>
        private void SessionForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (closeForm)
            {
                DialogResult result = MessageBox.Show(
                    "Stäng utan att spara?",
                    "Är du säker?",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question
                );

                if (result == DialogResult.Yes)
                    closeForm = false;
            }

            e.Cancel = closeForm;
        }


        /// <summary>
        /// Event-handler for the listbox.
        /// </summary>
        /// <param name="sender">A reference to the listbox.</param>
        /// <param name="e">Additional event information</param>
        private void lboxMuscles_MouseClick(object sender, MouseEventArgs e)
        {
            int muscleIndex = lboxMuscles.SelectedIndex;
            if (CheckIndex(muscleIndex))
            {
                string original = txtDescription.Text;
                string muscle = lboxMuscles.SelectedItem.ToString();
                if (original.Length > 0)
                {
                    original = original + "\r\n";
                }
                string newString = original + muscle + " - ";
                txtDescription.Text = newString;
            }
        }


        /// <summary>
        /// Event-handler for the ComboBox with muscle categories.
        /// </summary>
        /// <param name="sender">A reference to the combobox.</param>
        /// <param name="e">Additional event information</param>
        private void cboxMuscleCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            int categoryIndex = cboxMuscleCategories.SelectedIndex;
            if (CheckIndex(categoryIndex))
            {
                switch (categoryIndex)
                {
                    case 0:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(BackMuscles))); break;
                    case 1:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(ShoulderMuscles))); break;
                    case 2:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(SeatMuscles))); break;
                    case 3:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(HamstringsMuscles))); break;
                    case 4:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(CalfBackMuscles))); break;
                    case 5:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(QuadricepsFemorisMuscles))); break;
                    case 6:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(AdductorMuscles))); break;
                    case 7:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(CalfFrontMuscles))); break;
                    case 8:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(UpperArmMuscles))); break;
                    case 9:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(UnderArmMuscles))); break;
                    case 10:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(FacialMuscles))); break;
                    case 11:
                        UpdateMuscleListBox(GetMuscleEnumAsStrings(typeof(BreastMuscles))); break;
                }
            }
        }


        /// <summary>
        /// Event-handler for the Add button.
        /// </summary>
        /// <param name="sender">A reference to the add button.</param>
        /// <param name="e">Additional event information</param>
        private void btnSaveSession_Click(object sender, EventArgs e)
        {
            closeForm = false;
            bool result = ReadInput();
            
            if (result)
                closeForm = false;
        }


        /// <summary>
        /// Event-handler for the Clear input button.
        /// </summary>
        /// <param name="sender">A reference to the clear button.</param>
        /// <param name="e">Additional event information</param>
        private void btnClear_Click(object sender, EventArgs e)
        {
            ResetFields();
        }

        #endregion
    }
}
